package UIFree.command {
	import UIFree.ObjectEvent;
	
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	
	public class uif_commandManager extends EventDispatcher {
		private var _list		: Array;
		private var _index		: int;
		private var _workspace	: EventDispatcher;
		
		public static const EXECUTE		: String = 'EXECUTE';
		public static const UNDO		: String = 'UNDO';
		public static const REDO		: String = 'REDO';
		public static const CANEXECUTE	: String = 'CANEXECUTE';
		
		public function uif_commandManager(workspace: EventDispatcher) {
			super();
			_workspace = workspace;
			_workspace.addEventListener(EXECUTE, doExecute);
			_workspace.addEventListener(UNDO, doUndo);
			_workspace.addEventListener(REDO, doRedo);
			_list 	= new Array();
			_index 	= -1;
		}
		
		protected function doExecute(e: ObjectEvent): void {
			var command: ICommand = e.object as ICommand;
			canExecute(command, executeCommand);
		}
		
		protected function removeTopItems(startIndex: int): void {
			for (var i: int=startIndex; i<_list.length; i++) {
				_list[i].dispose();
			}
			_list.splice(startIndex, _list.length - startIndex);
			_index = _list.length - 1;
		}
		
		protected function executeCommand(command: ICommand): void {
			if (command) {
				if (_index < _list.length - 1) removeTopItems(_index + 1);
				
				command.Execute();
				
				_list.push(command);
				_index = _list.length - 1;
			}
		}
		
		protected function canExecute(a_command: ICommand, executeFunc: Function): void {
			var obj: Object = {
				command	: a_command,
				execute	: executeFunc,
				result	: true
			}
			_workspace.dispatchEvent(new ObjectEvent(CANEXECUTE, obj));
			if (obj.result) obj.execute(a_command);
			else a_command.noExecute();
		}
		
		protected function doUndo(e: Event): void {
			if (_index >= 0) {
				var command: ICommand = _list[_index];
				command.unExecute();
				_index--;
			}
		}
		
		protected function doRedo(e: Event): void {
			if (_index < _list.length - 1) {
				_index++;
				var command: ICommand = _list[_index];
				command.Execute();
			}
		}
		
		public function dispose(): void {
			removeTopItems(0);
		}
	}
}